home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 February / macformat-034.iso / mac / Shareware City / Developers / appe Windows 2.03 / sample drag.c < prev    next >
Encoding:
Text File  |  1995-10-29  |  7.6 KB  |  253 lines  |  [TEXT/CWIE]

  1. // File "sample drag.c" -
  2.  
  3. #include <Drag.h>
  4. #include <LowMem.h>
  5.  
  6. #include "main.h"
  7. #include "floaters.h"
  8. #include "sample drag.h"
  9. #include "sample win.h"
  10.  
  11. // ***********************************************************************************
  12. // Global Declarations 
  13.  
  14. extern GlobalsRec glob;
  15.  
  16. // ***********************************************************************************
  17. // ***********************************************************************************
  18.  
  19. void SetupDragHandlers(WindowPtr win) {
  20.     static DragTrackingHandlerUPP trackingHandler=0;
  21.     static DragReceiveHandlerUPP receiveHandler=0;
  22.  
  23.     if (! trackingHandler) trackingHandler = NewDragTrackingHandlerProc(SampleTrackingHandler);
  24.     if (! receiveHandler) receiveHandler = NewDragReceiveHandlerProc(SampleReceiveHandler);
  25.         
  26.     if (trackingHandler && receiveHandler) {
  27.         // Thanks to Mike Smith (msmith@pobox.com), who reminded me to properly set up
  28.         //   my globals environment in my handlers. I pass my own A5 in the refcon field
  29.         //   so that the callbacks can use *valid* static variables..
  30.         InstallTrackingHandler(trackingHandler, win, LMGetCurrentA5());
  31.         InstallReceiveHandler(receiveHandler, win, LMGetCurrentA5());
  32.         }
  33.     }
  34.  
  35. // ***********************************************************************************
  36. // ***********************************************************************************
  37.  
  38. short SampleWindowDrag(EventRecord *theEvent, WindowPtr win) {
  39.     short err=0;
  40.     Str255 textBuff;
  41.     RgnHandle dragRgn;
  42.     DragReference dragRef=0;
  43.     DragAttributes attributes;
  44.     
  45.     // If the user just clicks and lets go, then return
  46.     if (! WaitMouseMoved(theEvent->where)) return(0);
  47.     
  48.     // Setup the information we need to do a Drag
  49.     err = NewDrag(&dragRef);
  50.     if (err) return(err);
  51.  
  52.     dragRgn = NewDragRgn(win);
  53.     if (!dragRgn) goto HANDLE_ERROR;
  54.  
  55.     // Add in some data - The contents of our window
  56.     BlockMove(GetSampleWindowText(win), textBuff, sizeof(textBuff));
  57.     err = AddDragItemFlavor(dragRef, 1, 'TEXT', textBuff+1, textBuff[0], 0);    
  58.  
  59.  
  60.     // Initiate the dragging process, and handle any errors by escaping
  61.     err = TrackDrag(dragRef, theEvent, dragRgn);
  62.     if (err == userCanceledErr) err = 0;
  63.     if (err) goto HANDLE_ERROR;
  64.     
  65.     GetDragAttributes(dragRef, &attributes);
  66.     if (! (attributes & dragInsideSenderApplication)) {
  67.         AEDesc dropLocation;
  68.  
  69.         GetDropLocation(dragRef, &dropLocation);
  70.  
  71.         AEDisposeDesc(&dropLocation);
  72.         }
  73.  
  74.     
  75. HANDLE_ERROR:
  76.     if (dragRef) DisposeDrag(dragRef);
  77.     if (dragRgn) DisposeRgn(dragRgn);
  78.     return(err);
  79.     }
  80.  
  81. // ***********************************************************************************
  82. // ***********************************************************************************
  83.  
  84. pascal OSErr SampleTrackingHandler(DragTrackingMessage message, WindowPtr win,
  85.         long homeA5, DragReference dragRef) {
  86.     long saveA5 = SetA5(homeA5);
  87.     static Boolean acceptDrag, inContent;
  88.     short err=0;
  89.     unsigned short count;
  90.     unsigned long flavorFlags;
  91.     Size dataSize;
  92.     Point localPt;
  93.     GrafPtr savePort;
  94.     RgnHandle hiliteRgn;
  95.     ItemReference dragItem;
  96.     DragAttributes attributes;
  97.     
  98.     GetDragAttributes(dragRef, &attributes);
  99.     
  100.     GetPort(&savePort);
  101.     SetPort(win);
  102.     
  103.     switch (message) {
  104.         case dragTrackingEnterHandler:
  105.             acceptDrag = FALSE;
  106.             inContent = FALSE;
  107.             break;
  108.             
  109.         case dragTrackingEnterWindow:
  110.             // Test *every* Drag Item to see if it contains text or a text file.
  111.             //   (The sample code in the Drag Mgr dox suggested this, but I think
  112.             //   that you could probably reorganize it for whatever your needs are.)
  113.             if (CountDragItems(dragRef, &count)) count=0;
  114.             for(count, acceptDrag = TRUE; count && acceptDrag; count--) {
  115.                 GetDragItemReferenceNumber(dragRef, count, &dragItem);
  116.                 
  117.                 if (! GetFlavorFlags(dragRef, dragItem, 'TEXT', &flavorFlags)) continue;
  118.                 if (! GetFlavorFlags(dragRef, dragItem, 'hfs ', &flavorFlags)) {
  119.                     HFSFlavor hfsDataBuff;
  120.                     
  121.                     dataSize = sizeof(hfsDataBuff);
  122.                     err = GetFlavorData(dragRef, dragItem, 'hfs ', (Ptr) &hfsDataBuff, &dataSize, 0L);
  123.                     if (! err && (hfsDataBuff.fileType == 'TEXT')) continue;
  124.                     }
  125.                 
  126.                 acceptDrag = FALSE;
  127.                 }
  128.             break;
  129.  
  130.         case dragTrackingInWindow:
  131.             if (! acceptDrag) break;
  132.             
  133.             GetDragMouse(dragRef, &localPt, 0L);
  134.             GlobalToLocal(&localPt);
  135.             
  136.             if (attributes & dragHasLeftSenderWindow) {
  137.                 if (! inContent) {
  138.                     if (hiliteRgn = NewRgn()) {
  139.                         RectRgn(hiliteRgn, &win->portRect);
  140.                         ShowDragHilite(dragRef, hiliteRgn, TRUE);
  141.                         DisposeRgn(hiliteRgn);
  142.                         }
  143.                     inContent = TRUE;
  144.                     }
  145.                 }
  146.               else {
  147.                 if (inContent) {
  148.                     HideDragHilite(dragRef);
  149.                     inContent = FALSE;
  150.                     }
  151.                 }
  152.             break;
  153.         case dragTrackingLeaveWindow:
  154.             if (acceptDrag && inContent) HideDragHilite(dragRef);
  155.             acceptDrag = FALSE;
  156.             inContent = FALSE;
  157.             break;
  158.         case dragTrackingLeaveHandler:
  159.             break;
  160.         }
  161.  
  162.     SetPort(savePort);
  163.     SetA5(saveA5);
  164.     }
  165.  
  166. // ***********************************************************************************
  167. // ***********************************************************************************
  168.  
  169. pascal OSErr SampleReceiveHandler(WindowPtr win, long homeA5, DragReference dragRef) {
  170.     long saveA5 = SetA5(homeA5);
  171.     Boolean handled;
  172.     unsigned short index, count;
  173.     unsigned long flavorFlags;
  174.     Size dataSize;
  175.     Str255 textBuff;
  176.     GrafPtr savePort;
  177.     ItemReference dragItem;
  178.     DragAttributes attributes;
  179.  
  180.     // As above, we test every Drag Item to see if it contains text or text file. 
  181.     //   However, we simply find and use the first match (as the new window contents).
  182.     if (CountDragItems(dragRef, &count)) count=0;
  183.     for(index=1, handled=FALSE; (index<=count) && !handled; index++) {
  184.         GetDragItemReferenceNumber(dragRef, index, &dragItem);
  185.         
  186.         if (! GetFlavorFlags(dragRef, dragItem, 'TEXT', &flavorFlags)) {
  187.             GetFlavorDataSize(dragRef, dragItem, 'TEXT', &dataSize);
  188.             textBuff[0] = dataSize = (dataSize <= 255) ? dataSize : 255;
  189.             GetFlavorData(dragRef, dragItem, 'TEXT', (Ptr) textBuff+1, &dataSize, 0L);
  190.             handled = TRUE; continue;
  191.             }
  192.         
  193.         if (! GetFlavorFlags(dragRef, dragItem, 'hfs ', &flavorFlags)) {
  194.             short refNum, err=0;
  195.             HFSFlavor hfsDataBuff;
  196.             
  197.             dataSize = sizeof(hfsDataBuff);
  198.             err = GetFlavorData(dragRef, dragItem, 'hfs ', (Ptr) &hfsDataBuff, &dataSize, 0L);
  199.             if (hfsDataBuff.fileType != 'TEXT') err=-1;    // Only look at text files
  200.             if (! err) err = FSpOpenDF(&hfsDataBuff.fileSpec, fsRdPerm, &refNum);
  201.               else refNum = 0;
  202.             
  203.             dataSize = 255;
  204.             if (! err) err = FSRead(refNum, &dataSize, textBuff+1);
  205.             if (err == eofErr) err = 0;    // Short files are OK, ignore this error
  206.             if (refNum) FSClose(refNum);
  207.             
  208.             if (! err) textBuff[0] = dataSize;
  209.             if (! err) { handled = TRUE; continue; }
  210.             }
  211.         }
  212.     
  213.     if (handled) {
  214.         // Dirty the window, then help our app handle the event quickly.
  215.         //   (If you notice, we may be in someone else's context!)
  216.         SetSampleWindowText(win, textBuff);
  217.         WakeUpProcess(&glob.myPSN);
  218.         }
  219.     SetA5(saveA5);
  220.     return((handled) ? 0 : -1);
  221.     }
  222.  
  223. // ***********************************************************************************
  224. // ***********************************************************************************
  225.  
  226. RgnHandle NewDragRgn(WindowPtr win) {
  227.     Point convertPt;
  228.     GrafPtr savePort;
  229.     RgnHandle dragRgn=0, tempRgn=0;
  230.     
  231.     dragRgn = NewRgn();
  232.     tempRgn = NewRgn();
  233.     if (! dragRgn || ! tempRgn) return(0);
  234.     
  235.     // Build up a region that's 1 pixel thick, as per Drag Mgr dox
  236.     RectRgn(dragRgn, &win->portRect);
  237.     InsetRgn(dragRgn, 3, 3);
  238.     CopyRgn(dragRgn, tempRgn);
  239.     InsetRgn(tempRgn, 1, 1);
  240.     DiffRgn(dragRgn, tempRgn, dragRgn);
  241.     DisposeRgn(tempRgn);
  242.     
  243.     // Convert the coords of our rgn (ala PortRect) from Local to Global
  244.     GetPort(&savePort);
  245.     SetPort(win);
  246.     SetPt(&convertPt, 0, 0);
  247.     LocalToGlobal(&convertPt);
  248.     SetPort(savePort);
  249.     OffsetRgn(dragRgn, convertPt.h, convertPt.v);
  250.     
  251.     return(dragRgn);
  252.     }
  253.